#include <swapboom.h>
#include <cstdlib>
#include <ctime>
#include <queue>

using namespace std;

namespace {
struct Point
{
    int row;
    int col;
    Point(int row, int col) : row(row), col(col) {}
};
}

Swapboom::Swapboom()
{
    srand(time(NULL));
}

int Swapboom::getRows() const
{
    return cntRows;
}

int Swapboom::getColumns() const
{
    return cntColumns;
    return 0;
}

int Swapboom::setColumns(int cols)
{
    cntColumns = cols;
    return 0;
}

int Swapboom::setRows(int rows)
{
    cntRows = rows;
    return 0;
}

int Swapboom::getBooms() const
{
    return cntBooms;
}

void Swapboom::setBooms(int val)
{
    cntBooms = val;
}

int Swapboom::getState(int row, int col) const
{
    return stateMp[row][col];
}

int Swapboom::getNum(int row, int col) const
{
    int dr[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
    int dc[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
    int ans = 0;
    for (int i = 0; i < 8; i++) {
        int nowRow = row + dr[i];
        int nowCol = col + dc[i];
        if (nowRow < 0 || nowRow >= cntRows
                || nowCol < 0 || nowCol >= cntColumns) {
            continue;
        }
        if (mp[nowRow][nowCol] == Boom) {
            ans++;
        }
    }
    return ans;
}

void Swapboom::replay()
{
    for (int i = 0; i < cntRows; i++) {
        for (int j = 0; j < cntColumns; j++) {
            stateMp[i][j] = Closed;
        }
    }
    leftBooms = cntBooms;
}

void Swapboom::genMp()
{
    for (int i = 0; i < cntRows; i++) {
        for (int j = 0; j < cntColumns; j++) {
            mp[i][j] = None;
        }
    }
    int t = cntBooms;
    while (t--) {
        while (true) {
            int row = rand() % cntRows;
            int col = rand() % cntColumns;
            if (mp[row][col] == Boom)
                continue;
            mp[row][col] = Boom;
            break;
        }
    }
}

void Swapboom::openAll()
{
    for (int i = 0; i < cntRows; i++) {
        for (int j = 0; j < cntColumns;j++) {
            stateMp[i][j] = Opened;
        }
    }
}

bool Swapboom::open(int row, int col)
{
    if (stateMp[row][col] != Closed) {
        return false;
    }
    stateMp[row][col] = Opened;
    if (mp[row][col] == Boom) {
        failure();
        return true;
    }
    if (getNum(row, col) != 0) {
        return true;
    }

    static int dr[] = { -1, 1, 0, 0 };
    static int dc[] = { 0, 0, -1, 1 };
    queue<Point> q;
    q.push(Point(row, col));
    while (!q.empty()) {
        Point now = q.front();
        q.pop();
        for (int i = 0; i < 4; i++) {
            int nr = now.row + dr[i];
            int nc = now.col + dc[i];
            if (nr < 0 || nr >= cntRows || nc < 0 || nc >= cntColumns)
                continue;
            if (mp[nr][nc] == Boom || stateMp[nr][nc] == Marked
                    || stateMp[nr][nc] == Opened) {
                continue;
            }
            if (getNum(nr, nc) == 0) {
                stateMp[nr][nc] = Opened;
                q.push(Point(nr, nc));
            } else {
                stateMp[nr][nc] = Opened;
            }
        }
    }
    return true;
}

int Swapboom::isBoom(int row, int col) const
{
    return mp[row][col];
}

bool Swapboom::turnFlag(int row, int col)
{
    if (stateMp[row][col] == Opened) {
        return false;
    }
    if (stateMp[row][col] == Closed) {
        if (mp[row][col] == Boom) {
            leftBooms--;
        }
        stateMp[row][col] = Marked;
    } else {
        if (mp[row][col] == Boom) {
            leftBooms++;
        }
        stateMp[row][col] = Closed;
    }
    if (leftBooms == 0) {
        win();
    }
    return true;
}

void Swapboom::failure()
{
}


void Swapboom::win()
{

}

